package com.jie.client.core.handler;

import com.google.gson.reflect.TypeToken;
import com.jie.client.core.ClientApplication;
import com.jie.client.service.entity.model.Group;
import com.jie.client.service.entity.model.GroupChat;
import com.jie.client.service.entity.model.SingleChat;
import com.jie.client.service.entity.model.User;
import com.jie.client.service.entity.vo.FollowUserVo;
import com.jie.client.service.entity.vo.GroupChatVo;
import com.jie.client.service.entity.vo.SingleChatVo;
import com.jie.client.service.ui.constant.ViewMapConstant;
import com.jie.client.service.ui.model.ChatRecordNode;
import com.jie.client.service.ui.model.OnlineListNode;
import com.jie.client.service.ui.model.UserItemNode;
import com.jie.client.service.ui.util.AlertUtil;
import com.jie.client.service.ui.view.*;
import com.jie.client.service.ui.view.item.ChatRecordItem;
import com.jie.client.service.ui.view.item.FollowItem;
import com.jie.client.service.ui.view.item.GroupItem;
import com.jie.client.service.ui.view.item.UserItem;
import com.jie.common.http.constant.HttpHeaderLineNameConstant;
import com.jie.common.http.constant.response.HttpResponseStatusConstant;
import com.jie.common.http.constant.response.ServerResponseStatusConstant;
import com.jie.common.http.entity.response.HttpResponse;
import com.jie.common.util.JsonUtil;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.ListView;
import javafx.scene.control.TableView;
import javafx.scene.control.TextArea;
import javafx.stage.Stage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * http响应处理
 * @author XieZhiJie
 * @date 2022/04/23 16:05
 */
public class ClientReaderHandler {

    private static final Logger LOGGER = LoggerFactory.getLogger(ClientReaderHandler.class);

    /**
     * 客户端处理响应
     * @param httpResponse 响应
     */
    public static void handleResponse(HttpResponse httpResponse) {
        try {
            LOGGER.info("开始处理...");
            String statusCode = httpResponse.getStatusCode();
            if (!HttpResponseStatusConstant.SUCCESS.statusCode.equals(statusCode)) {
                AlertUtil.warn(httpResponse.getStatusDescription());
                LOGGER.info("结束处理...");
                return;
            }
            String serverStatus = httpResponse.getHeaderLineValue(HttpHeaderLineNameConstant.SERVER_RESPONSE_STATUS);
            if (serverStatus == null) {
                LOGGER.info(httpResponse.toString());
            } else {
                switch (serverStatus) {
                    case ServerResponseStatusConstant.REGISTER_SUCCESS:
                        handleRegisterSuccess(httpResponse);
                        break;
                    case ServerResponseStatusConstant.REGISTER_FAIL:
                        handleRegisterFail(httpResponse);
                        break;
                    case ServerResponseStatusConstant.LOGIN_SUCCESS:
                        handleLoginSuccess(httpResponse);
                        break;
                    case ServerResponseStatusConstant.LOGIN_FAIL:
                        handleLoginFail(httpResponse);
                        break;
                    case ServerResponseStatusConstant.GET_USER_INFO_SUCCESS:
                        handleGetUserInfoSuccess(httpResponse);
                        break;
                    case ServerResponseStatusConstant.GET_ONLINE_USER_LIST_SUCCESS:
                        handleGetOnlineUserListSuccess(httpResponse);
                        break;
                    case ServerResponseStatusConstant.UPDATE_USER_INFO_SUCCESS:
                    case ServerResponseStatusConstant.UPDATE_USER_INFO_FAIL:
                        handleUpdateUserInfo(httpResponse);
                        break;
                    case ServerResponseStatusConstant.CHAT_TO_ONE_SUCCESS:
                    case ServerResponseStatusConstant.CHAT_TO_ONE_FAIL:
                        handleChatToOne(httpResponse);
                        break;
                    case ServerResponseStatusConstant.CHAT_FROM_ONE_SUCCESS:
                        handleChatFromOneSuccess(httpResponse);
                        break;
                    case ServerResponseStatusConstant.CHAT_TO_ONE_RECORDS_SUCCESS:
                        handleChatToOneRecordsSuccess(httpResponse);
                        break;
                    case ServerResponseStatusConstant.BUILD_GROUP_SUCCESS:
                        handleBuildGroupSuccess(httpResponse);
                        break;
                    case ServerResponseStatusConstant.GET_GROUP_LIST_SUCCESS:
                        handleGetGroupListSuccess(httpResponse);
                        break;
                    case ServerResponseStatusConstant.GET_USER_GROUP_LIST_SUCCESS:
                        handleGetUserGroupListSuccess(httpResponse);
                        break;
                    case ServerResponseStatusConstant.UPDATE_GROUP_NAME_SUCCESS:
                    case ServerResponseStatusConstant.UPDATE_GROUP_NAME_FAIL:
                        handleUpdateGroupName(httpResponse);
                        break;
                    case ServerResponseStatusConstant.JOIN_GROUP_SUCCESS:
                        handleJoinGroupSuccess(httpResponse);
                        break;
                    case ServerResponseStatusConstant.JOIN_GROUP_FAIL:
                        handleJoinGroupFail(httpResponse);
                        break;
                    case ServerResponseStatusConstant.SIGN_OUT_GROUP_SUCCESS:
                        handleSignOutGroupSuccess(httpResponse);
                        break;
                    case ServerResponseStatusConstant.SING_OUT_GROUP_FAIL:
                        handleSignOutGroupFail(httpResponse);
                        break;
                    case ServerResponseStatusConstant.GET_GROUP_USER_LIST_SUCCESS:
                        handleGetGroupUserListSuccess(httpResponse);
                        break;
                    case ServerResponseStatusConstant.GET_GROUP_USER_LIST_FAIL:
                        handleGetGroupUserListFail(httpResponse);
                        break;
                    case ServerResponseStatusConstant.CHAT_TO_GROUP_SUCCESS:
                        handleChatToGroupSuccess(httpResponse);
                        break;
                    case ServerResponseStatusConstant.CHAT_TO_GROUP_FAIL:
                        handleChatToGroupFail(httpResponse);
                        break;
                    case ServerResponseStatusConstant.CHAT_FROM_GROUP_SUCCESS:
                        handleChatFromGroupSuccess(httpResponse);
                        break;
                    case ServerResponseStatusConstant.CHAT_FROM_GROUP_FAIL:
                        handleChatFromGroupFail(httpResponse);
                        break;
                    case ServerResponseStatusConstant.CHAT_TO_GROUP_RECORDS_SUCCESS:
                        handleChatToGroupRecordsSuccess(httpResponse);
                        break;
                    case ServerResponseStatusConstant.CHAT_TO_GROUP_RECORDS_FAIL:
                        handleChatToGroupRecordsFail(httpResponse);
                        break;
                    case ServerResponseStatusConstant.FOLLOW_ADD_SUCCESS:
                    case ServerResponseStatusConstant.FOLLOW_ADD_FAIL:
                        handleFollowAdd(httpResponse);
                        break;
                    case ServerResponseStatusConstant.GET_FOLLOW_USER_LIST_SUCCESS:
                        handleGetFollowUserListSuccess(httpResponse);
                        break;
                    case ServerResponseStatusConstant.GET_FOLLOW_USER_LIST_FAIL:
                        handleGetFollowUserListFail(httpResponse);
                        break;
                    case ServerResponseStatusConstant.GET_ONLINE_FOLLOW_USER_LIST_SUCCESS:
                        handleGetOnlineFollowUserListSuccess(httpResponse);
                        break;
                    case ServerResponseStatusConstant.GET_ONLINE_FOLLOW_USER_LIST_FAIL:
                        handleGetOnlineFollowUserListFail(httpResponse);
                        break;
                    case ServerResponseStatusConstant.CANCEL_FOLLOW_SUCCESS:
                    case ServerResponseStatusConstant.CANCEL_FOLLOW_FAIL:
                        handleCancelFollow(httpResponse);
                        break;
                    case ServerResponseStatusConstant.UPDATE_FOLLOW_SUCCESS:
                    case ServerResponseStatusConstant.UPDATE_FOLLOW_FAIL:
                        handleUpdateFollow(httpResponse);
                        break;
                    case ServerResponseStatusConstant.GET_NOT_FOLLOW_USER_LIST_SUCCESS:
                        handleGetNotFollowUserListSuccess(httpResponse);
                        break;
                    case ServerResponseStatusConstant.GET_NOT_FOLLOW_USER_LIST_FAIL:
                        handleGetNotFollowUserListFail(httpResponse);
                        break;
                    default:
                        LOGGER.info(httpResponse.toString());
                        break;
                }
            }
            LOGGER.info("结束处理...");
        } catch (Exception e) {
            LOGGER.warn("处理响应出错!");
        }
    }

    public static void handleRegisterSuccess(HttpResponse httpResponse) {
        AlertUtil.info(httpResponse.getEntityString());
        Stage primaryStage = (Stage) ClientApplication.VIEW_MAP.get(ViewMapConstant.MAIN_STAGE);
        // 返回登录页面
        if (primaryStage != null) {
            // 看了下注释, 将runnable加入到Platform.runLater, 是会按照顺序执行的
            Platform.runLater(() -> {
                primaryStage.setTitle("登录");
                primaryStage.setScene(new LoginView().getLoginScene());
                Platform.runLater(primaryStage::show);
            });
        }
    }

    public static void handleRegisterFail(HttpResponse httpResponse) {
        AlertUtil.warn(httpResponse.getEntityString());
    }

    public static void handleLoginSuccess(HttpResponse httpResponse) {
        ClientApplication.COOKIE = httpResponse.getHeaderLineValue(HttpHeaderLineNameConstant.COOKIE);
        Stage primaryStage = (Stage) ClientApplication.VIEW_MAP.get(ViewMapConstant.MAIN_STAGE);
        if (primaryStage != null) {
            // 弹出登录成功
            AlertUtil.info("登录成功!");
            User user = JsonUtil.fromJson(httpResponse.getEntityString(), User.class);
            ClientApplication.USER = user;
            // 关闭当前页面并打开主界面
            Platform.runLater(() -> {
                primaryStage.close();
                primaryStage.setTitle("主页面");
                primaryStage.setScene(new MainView().getMainView(user));
                primaryStage.show();
                // 获取在线用户
                Map<String, Object> map = new HashMap<>(2);
                map.put("choice", "getOnlineUserList");
                ClientWriteHandler.sendRequest(map);
            });
        }
    }

    public static void handleLoginFail(HttpResponse httpResponse) {
        Stage primaryStage = (Stage) ClientApplication.VIEW_MAP.get(ViewMapConstant.MAIN_STAGE);
        if (primaryStage != null) {
            // 打开主界面
            AlertUtil.warn(httpResponse.getEntityString());
        }
    }

    public static void handleGetUserInfoSuccess(HttpResponse httpResponse) {
        LOGGER.info("" + JsonUtil.fromJson(httpResponse.getEntityString(), User.class));
    }

    public static void handleGetOnlineUserListSuccess(HttpResponse httpResponse) {
        // 1.获取需要更新的组件
        OnlineListNode onlineListNode = (OnlineListNode) ClientApplication.VIEW_MAP.get(ViewMapConstant.ONLINE_LIST_NODE);
        if (onlineListNode == null) {
            return;
        }
        ListView<String> onlineListView = onlineListNode.onlineListView;
        List<User> onlineListDetailsData = onlineListNode.onlineListDetailsData;
        ObservableList<String> onlineListData = onlineListNode.onlineListData;
        if (onlineListView == null || onlineListData == null) {
            return;
        }
        List<User> userList = JsonUtil.fromJson(httpResponse.getEntityString(), new TypeToken<List<User>>() {}.getType());
        // 2.更新
        Platform.runLater(() -> {
            onlineListDetailsData.clear();
            onlineListData.clear();
            for (User user : userList) {
                onlineListDetailsData.add(user);
                String s = user.getUsername() + "(" + user.getUserAccount() + ")";
                if (Objects.equals(user.getUserId(), ClientApplication.USER.getUserId())) {
                    s = s + "(我)";
                }
                onlineListData.add(s);
            }
            onlineListView.setItems(onlineListData);
        });
    }

    public static void handleUpdateUserInfo(HttpResponse httpResponse) {
        System.out.println(httpResponse);
    }

    public static void handleChatToOne(HttpResponse httpResponse) {
        LOGGER.info(httpResponse.getEntityString());
    }

    public static void handleChatFromOneSuccess(HttpResponse httpResponse) {
        SingleChatVo singleChatVo = JsonUtil.fromJson(httpResponse.getEntityString(), SingleChatVo.class);
        // 判断是否存在和该用户的私聊窗口, 存在则填充信息否则不填充
        TextArea singleChatMessage = (TextArea) ClientApplication.VIEW_MAP.get("singleChatMessage" + singleChatVo.getSendUserId());
        if (singleChatMessage != null) {
            Platform.runLater(() -> {
                synchronized (singleChatMessage) {
                    singleChatMessage.appendText(
                            "\n" + singleChatVo.getSendUsername() + "(" + singleChatVo.getSendUserAccount() + ") "
                                    + singleChatVo.getSendTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + "\n"
                                    + singleChatVo.getChatMessage()
                    );
                }
            });
        }
    }

    public static void handleChatToOneRecordsSuccess(HttpResponse httpResponse) {
        List<SingleChat> singleChatRecordsList = JsonUtil.fromJson(httpResponse.getEntityString(), new TypeToken<List<SingleChat>>() {}.getType());
        if (singleChatRecordsList != null && singleChatRecordsList.size() > 0) {
            Integer otherUserId = singleChatRecordsList.get(0).getSendUserId().equals(Integer.parseInt(ClientApplication.COOKIE)) ? singleChatRecordsList.get(0).getReceiveUserId() : singleChatRecordsList.get(0).getSendUserId();
            ChatRecordNode chatRecordNode = (ChatRecordNode) ClientApplication.VIEW_MAP.get("singleChatRecords" + otherUserId);
            ObservableList<ChatRecordItem> chatRecordItemList = FXCollections.observableArrayList();
            // 封装信息
            for (SingleChat singleChat : singleChatRecordsList) {
                chatRecordItemList.add(new ChatRecordItem(singleChat.getId(), singleChat.getSendUserIdent(), singleChat.getChatMessage(), singleChat.getSendTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))));
            }
            Platform.runLater(() -> {
                if (chatRecordItemList.size() > 0) {
                    chatRecordNode.chatRecordsTable.setItems(chatRecordItemList);
                }
            });
        }
    }

    public static void handleBuildGroupSuccess(HttpResponse httpResponse) {
        AlertUtil.info(httpResponse.getEntityString());
        // 刷新一下群聊列表
        Map<String, Object> map = new HashMap<>();
        map.put("choice", "getUserGroupList");
        ClientWriteHandler.sendRequest(map);
    }

    public static void handleGetGroupListSuccess(HttpResponse httpResponse) {
        List<Group> groupList = JsonUtil.fromJson(httpResponse.getEntityString(), new TypeToken<List<Group>>() {}.getType());
        AllGroupView allGroupView = (AllGroupView) ClientApplication.VIEW_MAP.get(ViewMapConstant.ALL_GROUP_VIEW);
        if (allGroupView != null) {
            ListView<GroupItem> groupItemListView = allGroupView.allGroupView;
            setGroupToListView(groupList, groupItemListView);
        }
    }

    public static void handleGetUserGroupListSuccess(HttpResponse httpResponse) {
        List<Group> groupList = JsonUtil.fromJson(httpResponse.getEntityString(), new TypeToken<List<Group>>() {}.getType());
        GroupListView groupListView = (GroupListView) ClientApplication.VIEW_MAP.get(ViewMapConstant.GROUP_LIST_VIEW);
        if (groupListView != null) {
            ListView<GroupItem> groupItemListView = groupListView.groupItemListView;
            setGroupToListView(groupList, groupItemListView);
        }
    }

    private static void setGroupToListView(List<Group> groupList, ListView<GroupItem> groupItemListView) {
        ObservableList<GroupItem> groupIdsData = FXCollections.observableArrayList();
        Platform.runLater(() -> {
            for (Group group : groupList) {
                groupIdsData.add(new GroupItem(String.valueOf(group.getGroupId()), group.getGroupName()));
            }
            groupItemListView.setItems(groupIdsData);
        });
    }

    public static void handleUpdateGroupName(HttpResponse httpResponse) {
        System.out.println(httpResponse);
    }

    public static void handleJoinGroupSuccess(HttpResponse httpResponse) {
        AlertUtil.info(httpResponse.getEntityString());
        // 刷新一下群聊列表
        Map<String, Object> map = new HashMap<>();
        map.put("choice", "getUserGroupList");
        ClientWriteHandler.sendRequest(map);
    }

    public static void handleJoinGroupFail(HttpResponse httpResponse) {
        AlertUtil.warn(httpResponse.getEntityString());
    }

    public static void handleSignOutGroupSuccess(HttpResponse httpResponse) {
        AlertUtil.info(httpResponse.getEntityString());
        // 刷新一下群聊列表
        Map<String, Object> map = new HashMap<>();
        map.put("choice", "getUserGroupList");
        ClientWriteHandler.sendRequest(map);
    }

    public static void handleSignOutGroupFail(HttpResponse httpResponse) {
        AlertUtil.warn(httpResponse.getEntityString());
    }

    public static void handleGetGroupUserListSuccess(HttpResponse httpResponse) {
        Platform.runLater(() -> new GroupUserView(JsonUtil.fromJson(httpResponse.getEntityString(), new TypeToken<List<User>>() {}.getType())).createGroupUserView());
    }

    public static void handleGetGroupUserListFail(HttpResponse httpResponse) {
        System.out.println(httpResponse);
    }

    public static void handleChatToGroupSuccess(HttpResponse httpResponse) {
        LOGGER.trace(httpResponse.getEntityString());
    }

    public static void handleChatToGroupFail(HttpResponse httpResponse) {
        AlertUtil.warn(httpResponse.getEntityString());
    }

    public static void handleChatFromGroupSuccess(HttpResponse httpResponse) {
        GroupChatVo groupChatVo = JsonUtil.fromJson(httpResponse.getEntityString(), GroupChatVo.class);
        TextArea groupChatMessage = (TextArea) ClientApplication.VIEW_MAP.get("groupChatMessage" + groupChatVo.getGroupId());
        if (groupChatMessage != null) {
            Platform.runLater(() -> {
                synchronized (groupChatMessage) {
                    groupChatMessage.appendText(
                            "\n" + groupChatVo.getSendUsername() + "(" + groupChatVo.getSendUserAccount() + ") "
                                    + groupChatVo.getSendTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + "\n"
                                    + groupChatVo.getChatMessage()
                    );
                }
            });
        }
    }

    public static void handleChatFromGroupFail(HttpResponse httpResponse) {
        AlertUtil.warn(httpResponse.getEntityString());
    }

    public static void handleChatToGroupRecordsSuccess(HttpResponse httpResponse) {
        List<GroupChat> groupChatRecordsList = JsonUtil.fromJson(httpResponse.getEntityString(), new TypeToken<List<GroupChat>>() {}.getType());
        if (groupChatRecordsList != null && groupChatRecordsList.size() > 0) {
            Integer groupId = groupChatRecordsList.get(0).getGroupId();
            ChatRecordNode chatRecordNode = (ChatRecordNode) ClientApplication.VIEW_MAP.get("groupChatRecords" + groupId);
            ObservableList<ChatRecordItem> chatRecordItemList = FXCollections.observableArrayList();
            // 封装信息
            for (GroupChat groupChat : groupChatRecordsList) {
                chatRecordItemList.add(new ChatRecordItem(groupChat.getId(), groupChat.getSendUserIdent(), groupChat.getChatMessage(), groupChat.getSendTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))));
            }
            Platform.runLater(() -> {
                if (chatRecordItemList.size() > 0) {
                    chatRecordNode.chatRecordsTable.setItems(chatRecordItemList);
                }
            });
        }
    }

    public static void handleChatToGroupRecordsFail(HttpResponse httpResponse) {
        AlertUtil.warn(httpResponse.getEntityString());
    }

    public static void handleFollowAdd(HttpResponse httpResponse) {
        AlertUtil.info(httpResponse.getEntityString());
        // 刷新一下关注列表与非关注列表
        Map<String, Object> map = new HashMap<>(2);
        map.put("choice", "getFollowUserList");
        ClientWriteHandler.sendRequest(map);
        map = new HashMap<>(2);
        map.put("choice", "getNotFollowUserList");
        ClientWriteHandler.sendRequest(map);
    }

    public static void handleGetFollowUserListSuccess(HttpResponse httpResponse) {
        List<FollowUserVo> followUserVoList = JsonUtil.fromJson(httpResponse.getEntityString(), new TypeToken<List<FollowUserVo>>() {}.getType());
        FollowView followView = (FollowView) ClientApplication.VIEW_MAP.get(ViewMapConstant.FOLLOW_VIEW);
        if (followView != null) {
            TableView<FollowItem> followItemTableView = followView.followItemTableView;
            ObservableList<FollowItem> followData = FXCollections.observableArrayList();
            for (FollowUserVo followUserVo : followUserVoList) {
                followData.add(new FollowItem(String.valueOf(followUserVo.getUserId()), followUserVo.getUserAccount(), followUserVo.getUsername(), followUserVo.getUsername() + "(" + followUserVo.getUserAccount() + ")", followUserVo.getRemark()));
            }
            Platform.runLater(() -> followItemTableView.setItems(followData));
        }
    }

    public static void handleGetFollowUserListFail(HttpResponse httpResponse) {
        System.out.println(httpResponse);
    }

    public static void handleGetOnlineFollowUserListSuccess(HttpResponse httpResponse) {
        System.out.println(httpResponse);
        System.out.println("" + JsonUtil.fromJson(httpResponse.getEntityString(), new TypeToken<List<FollowUserVo>>() {}.getType()));
    }

    public static void handleGetOnlineFollowUserListFail(HttpResponse httpResponse) {
        System.out.println(httpResponse);
    }

    public static void handleCancelFollow(HttpResponse httpResponse) {
        AlertUtil.info(httpResponse.getEntityString());
        Map<String, Object> map = new HashMap<>(2);
        map.put("choice", "getFollowUserList");
        ClientWriteHandler.sendRequest(map);
    }

    public static void handleUpdateFollow(HttpResponse httpResponse) {
        AlertUtil.info(httpResponse.getEntityString());
        Map<String, Object> map = new HashMap<>(2);
        map.put("choice", "getFollowUserList");
        ClientWriteHandler.sendRequest(map);
    }

    public static void handleGetNotFollowUserListSuccess(HttpResponse httpResponse) {
        List<User> userList = JsonUtil.fromJson(httpResponse.getEntityString(), new TypeToken<List<User>>() {}.getType());
        UserItemNode stringListViewNode = (UserItemNode) ClientApplication.VIEW_MAP.get(ViewMapConstant.NOT_FOLLOW_USER_LIST);
        if (stringListViewNode != null) {
            ListView<UserItem> listView = stringListViewNode.listView;
            ObservableList<UserItem> notFData = FXCollections.observableArrayList();
            for (User user : userList) {
                notFData.add(new UserItem(Integer.parseInt(user.getUserId()), user.getUserAccount(), user.getUsername()));
            }
            Platform.runLater(() -> listView.setItems(notFData));
        }
    }

    public static void handleGetNotFollowUserListFail(HttpResponse httpResponse) {
        AlertUtil.warn(httpResponse.getEntityString());
    }

}
